package com.zlyx.easy.core.jackson;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.zlyx.easy.core.map.EasyMap;
import com.zlyx.easy.core.utils.StringUtils;

/**
 * <p>
 * Jackson工具
 * </p>
 *
 * @author 赵光
 * @since 2019年4月8日
 */
public class JSONObject extends EasyMap<String, Object> {

	private static final long serialVersionUID = 1L;

	private static final ObjectMapper objectMapper;

	private static final ObjectWriter objectWriter;

	static {
		objectMapper = new ObjectMapper();
		objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"));
		objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 反序列化时忽略不存在的属性
		objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 序列化时将LocalDateTime转换为时间戳格式
		objectMapper.registerModule(new JavaTimeModule());
		objectWriter = objectMapper.writer(new DefaultPrettyPrinter());
	}

	public JSONObject() {
	}

	public JSONObject(Map<String, Object> map) {
		super(map);
	}

	/**
	 * 返回JSONObject对象
	 *
	 * @param key
	 * @return
	 */
	public JSONObject getJSONObject(String key) throws IOException {
		return get(key) == null ? null : parseObject(getString(key), JSONObject.class);
	}

	/**
	 * 解析json字符串
	 *
	 * @param text
	 * @return
	 */
	public <T> T get(String key, Class<T> cls) throws IOException {
		return get(key) == null ? null : parseObject(getString(key), cls);
	}

	/**
	 * 解析json字符串
	 *
	 * @param key
	 * @param typeReference
	 * @return
	 * @throws Exception
	 */
	public <T> T get(String key, TypeReference<T> typeReference) throws Exception {
		return get(key) == null ? null : parseObject(getString(key), typeReference);
	}

	/**
	 * 解析json字符串
	 *
	 * @param text
	 * @return
	 */
	public static <T> T parseObject(String text, Class<T> cls) throws IOException {
		return StringUtils.isBlank(text) ? null : objectMapper.readValue(text, cls);
	}

	/**
	 * 解析json字符串
	 *
	 * @param text
	 * @param typeReference
	 * @return
	 * @throws Exception
	 */
	public static <T> T parseObject(String text, TypeReference<T> typeReference) throws Exception {
		return StringUtils.isBlank(text) ? null : objectMapper.readValue(text, typeReference);
	}

	/**
	 * 解析json字符串
	 *
	 * @param text
	 * @return
	 */
	public static JSONObject parseJSONObject(String text) throws IOException {
		return StringUtils.isBlank(text) ? null : new JSONObject(parseObject(text, JSONObject.class));
	}

	/**
	 * 对象转JSONObject
	 *
	 * @param o
	 * @return
	 * @throws IOException
	 */
	public static JSONObject toJSONObject(Object o) throws IOException {
		return o == null ? null : parseJSONObject(toString(o));
	}

	/**
	 * 对象转json字符串
	 *
	 * @param o
	 * @throws IOException
	 */
	public static String toJSONString(Object o) throws IOException {
		return o == null ? null : objectMapper.writeValueAsString(o);
	}

	/**
	 * 格式化输出对象
	 *
	 * @return
	 * @throws IOException
	 */
	public static String formatObject(Object o) throws IOException {
		return o == null ? null : objectWriter.writeValueAsString(o);
	}

	/**
	 * 对象转字符串
	 *
	 * @param o
	 * @return
	 */
	public static String toString(Object o) throws IOException {
		if (o == null) {
			return null;
		}
		if (o.getClass() == String.class) {
			return (String) o;
		}
		if (Number.class.isAssignableFrom(o.getClass())) {
			return String.valueOf(o);
		}
		return objectMapper.writeValueAsString(o);
	}

	/**
	 * 转list
	 *
	 * @param text
	 * @param <T>
	 * @return
	 * @throws IOException
	 */
	public static <T> List<T> toList(String text) throws IOException {
		return StringUtils.isBlank(text) ? null : objectMapper.readValue(text, new TypeReference<List<T>>() {
		});
	}

	/**
	 * 转map
	 *
	 * @param text
	 * @param <K>
	 * @param <V>
	 * @return
	 * @throws IOException
	 */
	public static <K, V> Map<K, V> toMap(String text) throws IOException {
		return StringUtils.isBlank(text) ? null : objectMapper.readValue(text, new TypeReference<Map<K, V>>() {
		});
	}

}
